package com.shoothzj.example.storage.ignite;

import com.shoothzj.example.storage.api.IDatabase;
import com.shoothzj.example.storage.api.module.TableInfo;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.client.ClientCacheConfiguration;
import org.apache.ignite.client.IgniteClient;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.stream.Collectors;

public class IgniteDatabaseService implements IDatabase {
    private final IgniteClient igniteClient;

    public IgniteDatabaseService(IgniteClient igniteClient) {
        this.igniteClient = igniteClient;
    }

    public void createSchema(String schema) {
        ClientCacheConfiguration cfg = new ClientCacheConfiguration();
        cfg.setName(schema);
        cfg.setSqlSchema("\"" + schema + "\"");
        igniteClient.getOrCreateCache(cfg);
    }

    public void createSchemaIgnoreCase(String schema) {
        ClientCacheConfiguration cfg = new ClientCacheConfiguration();
        cfg.setName(schema);
        cfg.setSqlSchema(schema);
        igniteClient.getOrCreateCache(cfg);
    }

    public void deleteSchema(String schema) {
        igniteClient.destroyCache(schema);
    }

    @Override
    public List<String> schemas() {
        List<List<?>> result = executeSql("SELECT SCHEMA_NAME FROM SYS.SCHEMAS");
        return result.stream().map(list -> (String) list.get(0)).collect(Collectors.toList());
    }

    public List<IgniteSchema> igniteSchemas() {
        List<List<?>> lists = executeSql("SELECT * FROM SYS.SCHEMAS");
        return lists.stream().map(IgniteDatabaseService::extractSchema).collect(Collectors.toList());
    }

    @Override
    public void createTable(String schema, String tableName, TableInfo tableInfo) {
    }

    public List<String> tables(String schema) {
        List<List<?>> result = executeSql("SELECT TABLE_NAME FROM SYS.TABLES WHERE SCHEMA_NAME = '" + schema + "'");
        return result.stream().map(list -> (String) list.get(0)).collect(Collectors.toList());
    }

    public long countTable(String schema, String tableName) {
        List<List<?>> result = executeSql("SELECT COUNT(*) FROM \"" + schema + "\".\"" + tableName + "\"");
        return (Long) result.get(0).get(0);
    }

    public List<IgniteIndex> indexes(String schema, String tableName) {
        List<List<?>> result = executeSql("SELECT * FROM SYS.INDEXES WHERE SCHEMA_NAME = '" + schema
                + "' AND TABLE_NAME = '" + tableName + "'");
        return result.stream().map(IgniteDatabaseService::extractIndex).collect(Collectors.toList());
    }

    @NotNull
    private static IgniteSchema extractSchema(List<?> list) {
        IgniteSchema igniteSchema = new IgniteSchema();
        igniteSchema.setSchema((String) list.get(0));
        igniteSchema.setPredefined((Boolean) list.get(1));
        return igniteSchema;
    }

    @NotNull
    private static IgniteIndex extractIndex(List<?> list) {
        IgniteIndex igniteIndex = new IgniteIndex();
        igniteIndex.setCacheGroupId((Integer) list.get(0));
        igniteIndex.setCacheGroupName((String) list.get(1));
        igniteIndex.setCacheId((Integer) list.get(2));
        igniteIndex.setCacheName((String) list.get(3));
        igniteIndex.setSchemaName((String) list.get(4));
        igniteIndex.setTableName((String) list.get(5));
        igniteIndex.setIndexName((String) list.get(6));
        igniteIndex.setIndexType((String) list.get(7));
        igniteIndex.setColumns((String) list.get(8));
        igniteIndex.setPk((Boolean) list.get(9));
        igniteIndex.setUnique((Boolean) list.get(10));
        igniteIndex.setInlineSize(IgniteUtil.nullableInteger(list.get(11)));
        return igniteIndex;
    }

    private List<List<?>> executeSql(String sql) {
        SqlFieldsQuery query = new SqlFieldsQuery(sql);
        return igniteClient.query(query).getAll();
    }
}
